package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.base.entity.bo.SciencePersonBo;
import com.base.mapper.SciencePersonMapper;
import com.common.api.ApprovalApi;
import com.common.api.CommonFileApi;
import com.common.core.domain.AjaxResult;
import com.common.utils.StringUtils;
import com.common.utils.bean.BizProcessMessages;
import com.feemanage.service.ISysSnruleService;
import com.flowable.service.IFlowInstanceService;
import com.project.comom.NumberDealUtils;
import com.project.domain.bo.ProjectTabListBo;
import com.project.domain.entity.*;
import com.project.mapper.SyntProjectMapper;
import com.project.mapper.UpLoadFileMapper;
import com.project.mapper.YfContractMapper;
import com.project.service.IProjectInitService;
import com.project.service.IYfContractDocumentService;
import com.project.service.IYfContractMemberService;
import com.project.service.IYfContractService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 横向进账合同
 */
@Service("biz_yf_contract")
public class YfContractServiceImpl extends ServiceImpl<YfContractMapper, BizYfContract> implements IYfContractService {
    /*横向项目进账 成员*/
    @Autowired
    private IYfContractMemberService yfMemberService;

    /*横向项目进账 文档*/
    @Autowired
    private IYfContractDocumentService yfDocumentService;

    @Autowired
    private YfContractMapper baseMapper;

    @Autowired
    private CommonFileApi fileApi;
    /*biz_person*/
    @Autowired
    private SciencePersonMapper personMapper;
    //文件上传
    @Autowired
    private UpLoadFileMapper fileMapper;
    //项目视图
    @Autowired
    private SyntProjectMapper projectMapper;
    //流程引擎
    @Autowired
    private IFlowInstanceService flowInstanceService;



    @Autowired
    BudgetStandardServiceImpl budgetStandardService;

    @Autowired
    ProjectBudgetServiceImpl  projectBudgetService;
    //发起流程
    @Autowired
    private ApprovalApi approvalApi;

    @Autowired
    private ISysSnruleService sysSnruleService;

    @Autowired
    private IProjectInitService projectInitService;

    private final static String module_name = "进账合同签订";


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveYfInfos(BizYfContract yfContract) {
        yfContract.setFeeAuthorize(NumberDealUtils.multiply_bigDecimal(yfContract.getFeeAuthorize()));
        //负责人id
        String chargerId = yfContract.getChargerCode();
        //负责人姓名
        String chargerName = yfContract.getChargerName();
        //负责人单位id
        String chargerUnitId = yfContract.getUnitId();
        //负责人单位名称
        String chargerUnitName = yfContract.getUnitName();

        yfContract.setAuthorpids(chargerId);
        yfContract.setAuthorunitids(chargerUnitId);
        //默认设置审核状态为-1
        yfContract.setCheckstatus("-1");
        //根据项目分类获取预算id
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式
            String authorizeDate = formatter.format(yfContract.getAuthorizeDate());
            yfContract.setBudgetStandardId(budgetStandardService.getYsbzIdByxmflId(yfContract.getContractType(),formatter.parse(authorizeDate)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        boolean saveBase = this.save(yfContract);
        String id = yfContract.getId();
        //默认添加负责人到成员表
        BizYfContractMember yfContractMember = new BizYfContractMember();
        yfContractMember.setContractId(id);
        yfContractMember.setPersonId(chargerId);
        //成员类型
        yfContractMember.setMemberType(yfContract.getChargerType());
        yfContractMember.setPersonName(chargerName);
        yfContractMember.setUnitId(chargerUnitId);
        yfContractMember.setUnitName(chargerUnitName);

        //如果是校内人员,给职称,学位,工号,职工号赋值
        if (StringUtils.isNotEmpty(chargerId)){
            SciencePersonBo person = getPerson(chargerId);
            yfContractMember.setTitleId(person.getTitleId());
            yfContractMember.setEduDegreeId(person.getEduDegreeId());
            yfContractMember.setCode(person.getAccount());
            yfContractMember.setPersonCode(person.getAccount());
        }

        //承担类型 默认1->负责人
        yfContractMember.setBearTypeId("1");
        //默认排序1
        yfContractMember.setOrderId(1L);


        boolean saveMember = yfMemberService.save(yfContractMember);
        return saveBase && saveMember ? yfContract.getId() : "";
    }

    @Override
    public AjaxResult editYfInfos(BizYfContract yfContract) {
        String proId = yfContract.getId();
        Integer submitType = yfContract.getSubmitType();
        String taskId = yfContract.getTaskId();
        //处理金额
        yfContract.setFeeAuthorize(NumberDealUtils.multiply_bigDecimal(yfContract.getFeeAuthorize()));
        //旧的基础页签
        BizYfContract oldInfos = this.getById(proId);

        //1.更换合同类别的情况
        //旧的合同类别
        String oldType = oldInfos.getContractType();
        //新的合同类别
        String newType = yfContract.getContractType();
        //删除旧的预算
        if(!oldType.equals(newType)){
            projectBudgetService.delBudgetInfos(proId);
        }
        //根据项目分类获取预算id
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式
            String authorizeDate = formatter.format(yfContract.getAuthorizeDate());
            yfContract.setBudgetStandardId(budgetStandardService.getYsbzIdByxmflId(yfContract.getContractType(),formatter.parse(authorizeDate)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        //2.合同经费发生变化的情况
        BigDecimal oldFee = oldInfos.getFeeAuthorize();
        BigDecimal newFee = yfContract.getFeeAuthorize();
        if (oldFee.compareTo(newFee) != 0){
            projectBudgetService.delBudgetInfos(proId);
        }

        //3.更换换负责人的情况
        String oldChargerName= oldInfos.getChargerName();
        String newChargerName = yfContract.getChargerName();
        //需要把合同成员表更新
        if (StringUtils.isNotEmpty(oldChargerName) && StringUtils.isNotEmpty(newChargerName) && !oldChargerName.equals(newChargerName)) {
            //负责人id
            String chargerCode =yfContract.getChargerCode();
            //负责人单位id
            String chargerUnitId = yfContract.getUnitId();
            //负责人单位名称
            String chargerUnitName = yfContract.getUnitName();

            SciencePersonBo  person = getPerson(chargerCode);
            person.setSysUserId(chargerCode);
            person.setName(yfContract.getChargerName());
            person.setUnitId(chargerUnitId);
            person.setUnitName(chargerUnitName);
            try {
                AjaxResult ajaxResult = changeCharge(proId, person, submitType, taskId,yfContract.getChargerType());
                String msg = (String)ajaxResult.get("MSG_TAG");
                if (StringUtils.isNotEmpty(msg) && msg.contains("失败")) return  AjaxResult.warn("处理负责人信息失败！");
            } catch (Exception e) {
               return    AjaxResult.warn("处理负责人信息失败！");
            }
        }

        boolean update = this.updateById(yfContract);
        if (!update) {
            return AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS);
        }
        return update ? projectInitService.saveAndCheck(proId, submitType,taskId) : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }

    //获取person部分未传的字段
    private SciencePersonBo getPerson(String chargerId){
        if (StringUtils.isEmpty(chargerId))   return new SciencePersonBo();
        LambdaQueryWrapper<SciencePersonBo> personLqw = new LambdaQueryWrapper<>();
        personLqw.select(SciencePersonBo::getTitleId,SciencePersonBo::getEduDegreeId,SciencePersonBo::getAccount)
                .eq(SciencePersonBo::getSysUserId,chargerId);
        return personMapper.selectOne(personLqw);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult saveYfMember(ProjectTabListBo<BizYfContractMember> projectMember) {
        //合同id
        String contractId = projectMember.getProId();
        //提交类型
        Integer submitType = projectMember.getSubmitType();
        //人员信息
        List<BizYfContractMember> yfContractMemberList = projectMember.getSlaveTableList();

        //1.先删除原有的成员,再添加
        LambdaUpdateWrapper<BizYfContractMember> luw = new LambdaUpdateWrapper<>();
        luw.eq(BizYfContractMember::getContractId, contractId);
        yfMemberService.remove(luw);

        //2.反写主表 -> 修改主表记录中的所有成员Id和所有人员的部门Id
        Set<String> personIds = new HashSet<>();
        Set<String> personUnits = new HashSet<>();
        //取出这些人员的id集合和部门集合
        for (int i = 0; i < yfContractMemberList.size(); i++) {
            //设置排序
            yfContractMemberList.get(i).setOrderId(i + 1L);

            //校外人员(memberType=3)处理
            if ("3".equals(yfContractMemberList.get(i).getMemberType())) {
                //校外人员保留成员信息，但不收集personId和unitId
                continue;
            }

            //非校外人员处理
            String personId = yfContractMemberList.get(i).getPersonId();
            if(StringUtils.isEmpty(personId)) {
                continue;
            }
            SciencePersonBo person = personMapper.selectOne(new QueryWrapper<SciencePersonBo>().eq("SYS_USER_ID", personId));
            if(person != null) {
                String unitId = person.getUnitId();
                personIds.add(personId);
                if (StringUtils.isNotEmpty(unitId)) {
                    personUnits.add(unitId);
                }
            }
        }


        Boolean saveContractMember = yfMemberService.saveBatch(yfContractMemberList);

        String authorpids_new = personIds.stream()
                .collect(Collectors.joining(","));
        String authorunitids_new = personUnits.stream()
                .collect(Collectors.joining(","));

        BizYfContract updateIdsAndUnitIds = new BizYfContract();
        updateIdsAndUnitIds.setAuthorpids(authorpids_new);
        updateIdsAndUnitIds.setAuthorunitids(authorunitids_new);
        updateIdsAndUnitIds.setId(contractId);
        //反写主表
        Boolean updateYfContract = this.updateById(updateIdsAndUnitIds);

        Boolean saveMember = updateYfContract && saveContractMember;

        return saveMember ? projectInitService.saveAndCheck(contractId, submitType,projectMember.getTaskId()) : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult saveYfFile(ProjectTabListBo<BizYfContractDocument> projectTabListBo) {
        String proId = projectTabListBo.getProId();
        if (StringUtils.isEmpty(proId)) return AjaxResult.error(BizProcessMessages.SAVE_FAIL);

        LambdaUpdateWrapper<BizYfContractDocument> yfQuery = new LambdaUpdateWrapper<>();
        yfQuery.eq(BizYfContractDocument::getContractId, proId);
        List<BizYfContractDocument> list = yfDocumentService.list(yfQuery);
        boolean remove = true;
        if (list != null && list.size() != 0) {
            LambdaUpdateWrapper<BizYfContractDocument> yfUpdate = new LambdaUpdateWrapper<>();
            yfUpdate.eq(BizYfContractDocument::getContractId, proId);
            remove = yfDocumentService.remove(yfUpdate);
        }

        List<BizYfContractDocument> documentList = projectTabListBo.getSlaveTableList();
        boolean baseAdd = true;
        if (documentList != null && documentList.size() != 0) {
            baseAdd = yfDocumentService.saveBatch(documentList);
        }
        Boolean saveFile = remove && baseAdd;

        return saveFile
                ? projectInitService.saveAndCheck(proId, projectTabListBo.getSubmitType(),projectTabListBo.getTaskId()) : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }

    /**
     * 基础页签更改了负责人
     * @param proId
     * @param person 新的负责人
     * @return
     */
    public AjaxResult changeCharge(String proId,SciencePersonBo person,Integer submitType,String taskId,String memberType){
        String newChargerCode = person.getSysUserId();
        LambdaQueryWrapper<BizYfContractMember> memberWrapper = new LambdaQueryWrapper<>();
        memberWrapper.eq(BizYfContractMember::getContractId,proId)
                .orderBy(true,true,BizYfContractMember::getOrderId);
        List<BizYfContractMember> contractMemberList = yfMemberService.list(memberWrapper);

        ProjectTabListBo<BizYfContractMember> projectMember = new ProjectTabListBo();
        projectMember.setSubmitType(submitType);
        projectMember.setProId(proId);
        projectMember.setTaskId(taskId);

        //原有成员列表为空
        if (CollectionUtils.isEmpty(contractMemberList)) {
            projectMember.setSlaveTableList(null);
            return this.saveYfMember(projectMember);
        }
            //是否校外
            boolean isInternal = StringUtils.isNotEmpty(newChargerCode);
            boolean hasPersonId = contractMemberList.stream()
                    .anyMatch(member -> isInternal ? newChargerCode.equals(member.getPersonId()) : person.getName().equals(member.getPersonName()));
            //新的负责人在原有成员列表里
            if(hasPersonId){
                // 找到第一个符合条件的记录
                Optional<BizYfContractMember> matchedMember = contractMemberList.stream()
                        .filter(member -> isInternal ? newChargerCode.equals(member.getPersonId())
                                : person.getName().equals(member.getPersonName()))
                        .findFirst();

                    matchedMember.ifPresent(newCharger -> {
                        // 如果当前第一位不是 newCharger,更新 memberType
                        if (!contractMemberList.isEmpty() && !contractMemberList.get(0).equals(newCharger)) {
                             contractMemberList.get(0).setBearTypeId("2");// 原负责人降级为主要参与人
                        }

                        // 移动并更新新负责人 ->删掉原有位置的数据,移动到第一位  并且设置为负责人
                        contractMemberList.remove(newCharger);
                        newCharger.setBearTypeId("1"); // 新负责人设为1 ->负责人
                        contractMemberList.add(0, newCharger);
                    });
                }else{
                    //降级旧负责人
                if (!contractMemberList.isEmpty()) {
                    contractMemberList.get(0).setBearTypeId("2");
                }

                //将基础页签的负责人 设置到人员表中,并且排在第一位
                BizYfContractMember newMember = createNewChargerMember(proId, person,memberType);
                contractMemberList.add(0, newMember);
            }
            projectMember.setSlaveTableList(contractMemberList);
            return this.saveYfMember(projectMember);

    }

    // 创建新负责人成员对象 -> 将基础页签的负责人设置到人员表中,并且排在第一位
    private BizYfContractMember createNewChargerMember(String proId, SciencePersonBo person,String memberType) {
        BizYfContractMember contractMember = new BizYfContractMember();
        contractMember.setContractId(proId);
        contractMember.setMemberType(memberType);
        contractMember.setPersonCode(person.getAccount());
        contractMember.setPersonId(person.getSysUserId());
        contractMember.setPersonName(person.getName());
        contractMember.setSexId(person.getSexId());
        contractMember.setUnitId(person.getUnitId());
        contractMember.setUnitName(person.getUnitName());
        contractMember.setTitleId(person.getTitleId());
        contractMember.setEduDegreeId(person.getEduDegreeId());
        contractMember.setOrderId(1L);
        contractMember.setBearTypeId("1");
        return contractMember;
    }


    @Override
    public BizYfContract getYfBase(String id) {
        BizYfContract yfContract = this.getById(id);
        //unitName赋值
        String unitId = yfContract.getUnitId();
        if (StringUtils.isNotEmpty(unitId)){
            String unitName = baseMapper.getUnitName(unitId);
            yfContract.setUnitName(unitName);
        }

        //处理金额
        yfContract.setFeeAuthorize(NumberDealUtils.divide_bigDecimal(yfContract.getFeeAuthorize()));
        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(module_name);
        //设置IsAuditor和TaskId
        String processInstanceId = yfContract.getProcessInstanceId();
        if (StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
            yfContract.setTaskId(instanceTaskMap.get(processInstanceId));
            yfContract.setIsAuditor(true);
        } else {
            yfContract.setIsAuditor(false);
        }

        //处理文件名
        String signature = yfContract.getSignature();
        List<Map<String, String>> signatureList = new ArrayList<>();
        if (StringUtils.hasText(signature)) {
            String[] split = signature.split(",");
            for (String s : split) {
                SysUploadFile uploadFile = fileMapper.selectById(s);
                if (uploadFile != null) {
                    Map<String, String> map = new HashMap<>();
                    map.put("id", s);
                    map.put("name", uploadFile.getUploadfilename());
//                    String url = serverConfig.getUrl() + fileName;
                    signatureList.add(map);
                }
            }

            yfContract.setSignatureList(signatureList);
        }
        return yfContract;
    }


    /**
     * 批量删除横向进账合同
     *
     * @param proId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String delYfInfos(String proId) {
        String res = "删除成功！";
        if (StringUtils.isEmpty(proId)) return res;
        List proIds = Arrays.asList(proId.split(","));
        //1.删除成员信息
        this.delYfMember(proIds);
        //2.删除文件信息
        this.delYfFile(proIds);
        //3.删除本身记录
        Boolean delYfBase = baseMapper.deleteBatchIds(proIds) > 0;
        //4.删除发起的流程引擎
//        this.delFlowable(proIds);

        return delYfBase ? res : "删除成功";
    }

    /**
     * 批量删除横向文件记录以及附带的文件
     *
     * @param proIds 合同表id
     * @return
     */
    public Boolean delYfFile(List<String> proIds) {
        LambdaQueryWrapper<BizYfContractDocument> documentQuery = new LambdaQueryWrapper();
        documentQuery.in(proIds != null && proIds.size() != 0, BizYfContractDocument::getContractId, proIds);
        List<BizYfContractDocument> documents = yfDocumentService.list(documentQuery);
        List<String> documentIds = new ArrayList();
        List<String> documentFileIds = new ArrayList();
        documents.forEach(e -> {
            documentIds.add(e.getId());
            documentFileIds.add(e.getFileId());
        });
        //删除文档本身信息
        boolean delDocumentBase = yfDocumentService.removeByIds(documentIds);
        //删除携带的文件
        documentFileIds.forEach(e -> {
            try {
                fileApi.delFile(e);
            } catch (Exception ex) {
                log.error("进账合同模块删除文件失败,文件id:"+e);
            }
        });

        return delDocumentBase;
    }


    /**
     * 批量删除横向记录 成员信息
     *
     * @param proIdList 主键id
     * @param
     * @return
     */
    public Boolean delYfMember(List<String> proIdList) {
        LambdaUpdateWrapper<BizYfContractMember> memberUpdate = new LambdaUpdateWrapper();
        memberUpdate.in(proIdList != null && proIdList.size() != 0, BizYfContractMember::getContractId, proIdList);
        boolean delFyMember = yfMemberService.remove(memberUpdate);
        return delFyMember;
    }


    /**
     * 批量删除流程引擎
     *
     * @param proIdList id
     * @param
     * @return
     */
    public void delFlowable(List<String> proIdList) {
        if (proIdList == null || proIdList.size() == 0) return;
        LambdaQueryWrapper<SyntProject> projectQuery = new LambdaQueryWrapper();
        projectQuery.select(SyntProject::getProcessInstanceId);
        projectQuery.in(SyntProject::getId, proIdList);
        List<SyntProject> projects = projectMapper.selectList(projectQuery);
        projects.forEach(e -> {
            String processInstanceId = e.getProcessInstanceId();
            if (!"0".equals(processInstanceId) && StringUtils.isNotEmpty(processInstanceId)) {
                flowInstanceService.delete(e.getProcessInstanceId(), "删除原数据");
            }
        });

    }


    @Override
    public List<BizYfContractDocument> getYfDocumentByProId(String proId) {
        return yfDocumentService.list(new LambdaQueryWrapper<BizYfContractDocument>().eq(StringUtils.isNotEmpty(proId), BizYfContractDocument::getContractId, proId));
    }

    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        if (checkStatus.equals("2")) {
            String proCode = sysSnruleService.generateCode("2", businessId);
            BizYfContract bizYfContract = new BizYfContract();
            bizYfContract.setCode(proCode);
            bizYfContract.setId(businessId);
            baseMapper.updateById(bizYfContract);
        }
    }
}
